#include <iostream>
#include <stdio.h>

class Base
{
	public:
		virtual void function_1()
		{
			printf("Base function_1...\n");
		}

		virtual void function_2()
		{
			printf("Base function_2...\n");
		}
	
		virtual void function_3()
		{
			printf("Base function_3...\n");
		}
};

class Sub : public Base
{
	public:
		virtual void function_4()
		{
			printf("Sub function_4...\n");
		}

		virtual void function_5()
		{
			printf("Sub function_5...\n");
		}
	
		virtual void function_6()
		{
			printf("Sub function_6...\n");
		}
};

int main(int argc, char ** argv)
{
	Sub sub;

	printf("sizeof = %ld\n",  sizeof(class Base));		/* 4 */
	printf("sizeof = %ld\n",  sizeof(class Sub));		/* 4 */

	printf("sub address is %x.\n", &sub);		// this 指针，是堆栈里面的地址。虚表的地址不是this指针，是this指针的前四个字节。
	printf("sub virtual table address is:%x\n", *(int*)&sub);   	// 虚表地址。取this指针的前4个字节。*(char*)&base为取一个字节。	

	typedef void(*pfunction)(void);
	
	pfunction pf;

	int temp = *((int*)(*(int*)&sub) + 0);		// 取地址表里面的第一个值
							// *(int*)&sub) 是虚表地址
							// (int*) 转换成一个int*类型。
							// *((int*)(*(int*)&sub) + 0)， 加的是0，即取第一个4字节值。
	pf = (pfunction)*((int*)(*(int*)&sub) + 0);	// 或这样，取地址表里面的第一个值
	pf();						// function_1

	pf = (pfunction)*((int*)(*(int*)&sub) + 1);	// 取第二个4字节值
	pf();						// function_2

	for (int i = 0; i < 6; i++) {
		pf = (pfunction)*((int*)(*(int*)&sub) + i);
		pf();
	}
}

#if 0

1.因为没有重写关系。

sub对象

	---------------		-------------
	| 0x123245    |	--->   	| 0x123456  |	Base:function_1
	---------------		-------------
	| ....        |		| 0x123457  |	Base:function_2
	---------------		-------------
	| ....	      |		| 0x123458  |	Base:function_3
	---------------		-------------
	| ....        |		| 0x123457  |	Sub:function_4
	---------------		-------------
	| ....	      |		| 0x123457  |	Sub:function_5
	---------------		-------------
	| 其它成员     |		| 0x123457  |	Sub:function_6
	---------------		-------------
	| ....	      |		| 0x000000  |
	---------------		-------------

int main(int argc, char ** argv)
{
 80486b0:	55                   	push   %ebp
 80486b1:	89 e5                	mov    %esp,%ebp
 80486b3:	83 e4 f0             	and    $0xfffffff0,%esp
 80486b6:	83 ec 20             	sub    $0x20,%esp
	Sub sub;
 80486b9:	8d 44 24 10          	lea    0x10(%esp),%eax
 80486bd:	89 04 24             	mov    %eax,(%esp)
 80486c0:	e8 a3 01 00 00       	call   8048868 <_ZN3SubC1Ev>

	printf("sizeof = %ld\n",  sizeof(class Base));		/* 4 */
 80486c5:	c7 44 24 04 04 00 00 	movl   $0x4,0x4(%esp)
 80486cc:	00 
 80486cd:	c7 04 24 9b 89 04 08 	movl   $0x804899b,(%esp)
 80486d4:	e8 a7 fe ff ff       	call   8048580 <printf@plt>
	printf("sizeof = %ld\n",  sizeof(class Sub));		/* 4 */
 80486d9:	c7 44 24 04 04 00 00 	movl   $0x4,0x4(%esp)
 80486e0:	00 
 80486e1:	c7 04 24 9b 89 04 08 	movl   $0x804899b,(%esp)
 80486e8:	e8 93 fe ff ff       	call   8048580 <printf@plt>

	printf("sub address is %x.\n", &sub);		// this 指针，是堆栈里面的地址。虚表的地址不是this指针，是this指针的前四个字节。
 80486ed:	8d 44 24 10          	lea    0x10(%esp),%eax
 80486f1:	89 44 24 04          	mov    %eax,0x4(%esp)
 80486f5:	c7 04 24 a9 89 04 08 	movl   $0x80489a9,(%esp)
 80486fc:	e8 7f fe ff ff       	call   8048580 <printf@plt>
	printf("sub virtual table address is:%x\n", *(int*)&sub);   	// 虚表地址。取this指针的前4个字节。*(char*)&base为取一个字节。	
 8048701:	8d 44 24 10          	lea    0x10(%esp),%eax
 8048705:	8b 00                	mov    (%eax),%eax
 8048707:	89 44 24 04          	mov    %eax,0x4(%esp)
 804870b:	c7 04 24 c0 89 04 08 	movl   $0x80489c0,(%esp)
 8048712:	e8 69 fe ff ff       	call   8048580 <printf@plt>

	typedef void(*pfunction)(void);
	
	pfunction pf;

	int temp = *((int*)(*(int*)&sub) + 0);		// 取地址表里面的第一个值
 8048717:	8d 44 24 10          	lea    0x10(%esp),%eax
 804871b:	8b 00                	mov    (%eax),%eax
 804871d:	8b 00                	mov    (%eax),%eax
 804871f:	89 44 24 18          	mov    %eax,0x18(%esp)
							// *(int*)&sub) 是虚表地址
							// (int*) 转换成一个int*类型。
							// *((int*)(*(int*)&sub) + 0)， 加的是0，即取第一个4字节值。
	pf = (pfunction)*((int*)(*(int*)&sub) + 0);	// 或这样，取地址表里面的第一个值
 8048723:	8d 44 24 10          	lea    0x10(%esp),%eax
 8048727:	8b 00                	mov    (%eax),%eax
 8048729:	8b 00                	mov    (%eax),%eax
 804872b:	89 44 24 14          	mov    %eax,0x14(%esp)
	pf();						// function_1
 804872f:	8b 44 24 14          	mov    0x14(%esp),%eax
 8048733:	ff d0                	call   *%eax

	pf = (pfunction)*((int*)(*(int*)&sub) + 1);	// 取第二个4字节值
 8048735:	8d 44 24 10          	lea    0x10(%esp),%eax
 8048739:	8b 00                	mov    (%eax),%eax
 804873b:	83 c0 04             	add    $0x4,%eax
 804873e:	8b 00                	mov    (%eax),%eax
 8048740:	89 44 24 14          	mov    %eax,0x14(%esp)
	pf();						// function_2
 8048744:	8b 44 24 14          	mov    0x14(%esp),%eax
 8048748:	ff d0                	call   *%eax

	for (int i = 0; i < 6; i++) {
 804874a:	c7 44 24 1c 00 00 00 	movl   $0x0,0x1c(%esp)
 8048751:	00 
 8048752:	eb 24                	jmp    8048778 <main+0xc8>
		pf = (pfunction)*((int*)(*(int*)&sub) + i);
 8048754:	8b 44 24 1c          	mov    0x1c(%esp),%eax
 8048758:	8d 14 85 00 00 00 00 	lea    0x0(,%eax,4),%edx
 804875f:	8d 44 24 10          	lea    0x10(%esp),%eax
 8048763:	8b 00                	mov    (%eax),%eax
 8048765:	01 d0                	add    %edx,%eax
 8048767:	8b 00                	mov    (%eax),%eax
 8048769:	89 44 24 14          	mov    %eax,0x14(%esp)
		pf();
 804876d:	8b 44 24 14          	mov    0x14(%esp),%eax
 8048771:	ff d0                	call   *%eax
	pf();						// function_1

	pf = (pfunction)*((int*)(*(int*)&sub) + 1);	// 取第二个4字节值
	pf();						// function_2

	for (int i = 0; i < 6; i++) {
 8048773:	83 44 24 1c 01       	addl   $0x1,0x1c(%esp)
 8048778:	83 7c 24 1c 05       	cmpl   $0x5,0x1c(%esp)
 804877d:	7e d5                	jle    8048754 <main+0xa4>
		pf = (pfunction)*((int*)(*(int*)&sub) + i);
		pf();
	}
}
 804877f:	b8 00 00 00 00       	mov    $0x0,%eax
 8048784:	c9                   	leave  
 8048785:	c3                   	ret    

#endif
